﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using Model;
using Model.Modules;
using Newtonsoft.Json;
using Org.BouncyCastle.Crypto.Modes.Gcm;
using Proxy;
using Utility;
using static ViewModel.VM_PageHistory;

namespace ViewModel.VM
{
    public class VM_PageReviewDefect : BaseViewModel
    {
        #region 变量
        public DateTime Start { get { return start; } set { start = value; OnPropertyChanged(); } }
        private DateTime start;
        public DateTime End { get { return end; } set { end = value; OnPropertyChanged(); } }
        private DateTime end;

        public bool IsFree { get { return isFree; } set { isFree = value; OnPropertyChanged(); } }
        private bool isFree;

        public int CurrentImageType
        {
            get { return currentImageType; }
            set
            {
                currentImageType = value;
                OnPropertyChanged();
                updateImage();
            }
        }
        private int currentImageType;


        public ObservableCollection<Imagedefectinfo> ImageInfolist
        {
            get { return imageinfolist; }
            set
            {
                imageinfolist = value; OnPropertyChanged();
                PageTotal = ImageInfolist.Count();
            }
        }
        private ObservableCollection<Imagedefectinfo> imageinfolist;
        public Imagedefectinfo CurrentImg
        {
            get { return currentImg; }
            set
            {
                currentImg = value;
                OnPropertyChanged();
            }
        }
        private Imagedefectinfo currentImg;


        public ObservableCollection<image_defect> Defectlist
        {
            get { return defectlist; }
            set
            {
                defectlist = value; OnPropertyChanged();
            }
        }
        private ObservableCollection<image_defect> defectlist;
        public image_defect CurrentDefect
        {
            get { return currentDefect; }
            set
            {
                currentDefect = value;
                OnPropertyChanged();
                QueryCurrentImg();
            }
        }


        private image_defect currentDefect;

        public int PageNum { get { return pageNum; } set { pageNum = value; OnPropertyChanged(); } }
        private int pageNum;
        public int PageTotal { get { return pageTotal; } set { pageTotal = value; OnPropertyChanged(); } }
        private int pageTotal;

        public int CurrentIndex { get { return currentIndex; } set { currentIndex = value; OnPropertyChanged(); PageNum = CurrentIndex + 1; } }
        private int currentIndex;

        public int ShownType { get { return shownType; } set { shownType = value; OnPropertyChanged(); } }
        private int shownType;

        public ObservableCollection<batch> Batchlist { get { return batchlist; } set { batchlist = value; OnPropertyChanged(); } }
        private ObservableCollection<batch> batchlist;
        public ObservableCollection<DefectCount> DefectCountList { get { return defectCountList; } set { defectCountList = value; OnPropertyChanged(); } }
        private ObservableCollection<DefectCount> defectCountList;
        public ObservableCollection<image_defect> SelectedImageDefects { get; set; }

        public bool IsAdmin { get { return StaticData.IsAdmin; } }


        public batch CurrentBatch
        {
            get { return currentBatch; }
            set
            {

                currentBatch = value;
                OnPropertyChanged();
                if (isInit&& currentBatch!=null)
                {
                    StaticData.TestEntitity = new TestEntitity(CurrentBatch.main_id);
                    var image_defectlist = ImageInfolist.SelectMany(t => t.Image_DefectList).Where(t => !string.IsNullOrEmpty(t.other1));
                    //每次更新批次前先判断提示保存缺陷
                    if (image_defectlist.Any())
                    {
                        MessageBox("是否保存修改", "原有批次存在未保存修改，是否保存", (save) =>
                        {
                            if (save)
                            {
                                SaveDefect();
                            }
                        });
                    }


                    ImageInfolist.Clear();
                    QueryImageList();

                }

            }
        }
        private batch currentBatch;



        public static surfacedetectEntities surfaceEntities;
        bool isInit = false;
        ESDataHelper eshelper = new ESDataHelper();
        #endregion

        public VM_PageReviewDefect(Imagedefectinfo Imagedefectinfo)
        {

            initData(Imagedefectinfo);

        }
        public VM_PageReviewDefect()
        {

            initData(null);
        }

        private void initData(Imagedefectinfo currentImagedefectinfo)
        {
            IsFree = true;
            ImageInfolist = new ObservableCollection<Imagedefectinfo>();
            SelectedImageDefects = new ObservableCollection<image_defect>();
            Start = DateTime.Now.AddDays(-10);
            End = DateTime.Now;
            CurrentImageType = 1;
            if (currentImagedefectinfo == null)
            {

            }
            surfaceEntities = new surfacedetectEntities();
            ShownType = 1;
            isInit = true;
            QueryBatchList();
            //CurrentImg = ImageInfolist.Where(t=> t.Image!=null&&t.Image.id==currentImagedefectinfo.Image.id).FirstOrDefault();
            //CurrentIndex =ImageDefectlist.IndexOf(CurrentImg);
            CloseCallBack = (s, e) =>
            {
                //SaveDefect();
            };
            StaticData.StaticPropertyChanged += (sender, e) =>
            {
                OnPropertyChanged(nameof(IsAdmin));
            };
        }

        //private ObservableCollection<Imagedefectinfo>
        //List(string mainid, int imagetype) {
        //    var _iamgelist = new List<image>();
        //    var _defectlist = new List<image_defect>();
        //    var _panolist = new List<panoramic_table>();
        //    if (StaticData.DataBase == DataFrom.ES)
        //    {
        //        _iamgelist = eshelper.GetImagesByMainID(mainid).Where(t => t.type == imagetype).ToList();
        //        _defectlist = eshelper.GetDefectsByMainID(mainid).ToList();
        //    }
        //    else if (StaticData.DataBase == DataFrom.Test)
        //    {
        //        TestEntitity testEntitity = new TestEntitity(mainid);
        //        _iamgelist = testEntitity.Imagelist.Where(t => t.type == imagetype).ToList();
        //        _defectlist = testEntitity.Defectlist.ToList();
        //    }
        //    var imageinfolist = new List<Imagedefectinfo>();
        //    foreach (var defect in _defectlist)
        //    {
        //        Imagedefectinfo info = new Imagedefectinfo();
        //        info.Defect = defect;
        //        var tempimagelist = _iamgelist.Where(t => t.id == defect.image_id);
        //        if (tempimagelist.Count() != 1)
        //        {
        //            Logger.Info($"一个缺陷未对应一张图片：{defect.defect_id}有{tempimagelist.Count()}个图片");
        //            continue;
        //        }
        //        else
        //        {
        //            var image = _iamgelist.Where(t => t.id == defect.image_id).First();
        //            image.image_url = image.image_url.Replace('/', '\\');
        //            info.Image = image;
        //            imageinfolist.Add(info);
        //        }

        //    }
        //    imageinfolist = new List<Imagedefectinfo>(imageinfolist.OrderBy(t => t.Image.flow_id.Length).ThenBy(t1 => t1.Image.flow_id));
        //    return new ObservableCollection<Imagedefectinfo>(imageinfolist);

        //}

        public void SaveDefect()
        {
            //if (StaticData.DataBase == DataFrom.Test)
            //    return;
            var image_defectlist = ImageInfolist.SelectMany(t => t.Image_DefectList).Where(t => !string.IsNullOrEmpty(t.other1)).ToArray();
            var savefailedDefects = new List<image_defect>();
            if (!image_defectlist.Any())
            {
                MessageBox("未做任何修改");
                return;
            }
            int addcount = 0, modifycount = 0, delcount = 0, failed = 0;
            try
            {
                foreach (var image_Defect in image_defectlist)
                {
                    switch (image_Defect.other1)
                    {

                        case "new":
                            image_Defect.other0 = image_Defect.other1;
                            image_Defect.other1 = "";
                            if (eshelper.AddDefect(image_Defect))
                                addcount++;
                            else
                                failed++; savefailedDefects.Add(image_Defect);
                            break;
                        case "modify":
                            image_Defect.other0 = image_Defect.other1;
                            image_Defect.other1 = "";
                            if (eshelper.UpdateDefect(image_Defect))
                                modifycount++;
                            else
                                failed++; savefailedDefects.Add(image_Defect);
                            break;
                        case "delete":
                            image_Defect.other0 = image_Defect.other1;
                            image_Defect.other1 = "";
                            if (eshelper.DeleteDefect(image_Defect))
                                delcount++;
                            else
                                failed++; savefailedDefects.Add(image_Defect);
                            break;
                    }
                }
                MessageBox($"保存完成，添加{addcount}个，修改{modifycount}个，删除{delcount}个");
                if (failed > 0)
                {
                    buckupDefectInfo(savefailedDefects);
                    MessageBox($"有{failed}条修改记录保存失败,已经备份到本地");
                }

                
                var modifiedimages = ImageInfolist.Where(t => image_defectlist.Select(s => s.image_id).Contains(t.Image.id));
                foreach (var modifiedimage in modifiedimages)
                {
                    modifiedimage.UpdateDefectCount();
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
            }

        }
        public void buckupDefectInfo(List<image_defect> defect) {
            var defectstr = JsonConvert.SerializeObject(defect);
            if(!Directory.Exists(Environment.CurrentDirectory + "\\backupDefects"))
                Directory.CreateDirectory(Environment.CurrentDirectory + "\\backupDefects");
            File.WriteAllText(Environment.CurrentDirectory+"\\backupDefects\\"+ DateTime.Now.ToString("yyyyMMdd-HHmmssFFF"), defectstr);
            
        }


        private async void QueryImageList()
        {
            IsFree = false;
            ImageInfolist.Clear();
            CurrentImg = null;
            var size = 20;
            int flowid = 1;
            await Task.Run(async () =>
            {

                var defectlist = new List<image_defect>();

                while (true)
                {
                    size = flowid < 20 ? 20 : 100;
                    var list = await new DefectDataHelper().getImageInfoList(CurrentBatch.main_id, size, flowid);
                    list.All(imageinfo => { imageinfo.ImageStatus = ImageInfoHelper.GetImageStatus(CurrentBatch.img_status); return true; });
                    new DefectDataHelper().setCurrentImageByImageType(list, CurrentImageType);
                    if (list.Count == 0)
                        break;
                    flowid = flowid + size;
                    _ = Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        AddImages(ImageInfolist, list);
                        if (size == 20 && ImageInfolist.Any())
                        {
                            CurrentImg = ImageInfolist.First();
                        }
                    }));
                    var defects = new ObservableCollection<image_defect>(list.SelectMany(t => t.Image_DefectList));
                    defectlist.AddRange(defects);
                    Thread.Sleep(50);
                }

                await Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                {
                    Defectlist = new ObservableCollection<image_defect>(defectlist.OrderByDescending(t => t.confidence));
                }));

                var defectcountlist_groupbytype = new ObservableCollection<DefectCount>(ImageInfolist.ToArray().SelectMany(t => t.Image_DefectList).GroupBy(t => t.type).Select(t => new DefectCount { DefectType = t.Key, Count = t.Count() }));

                await Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                {
                    DefectCountList = defectcountlist_groupbytype;
                    IsFree = true;
                }));

            });



        }
        public void AddImages(ObservableCollection<Imagedefectinfo> currentlist, IList<Imagedefectinfo> addeddata)
        {

            foreach (var item in addeddata)
            {
                currentlist.Add(item);
            }
        }

        public void updateImage()
        {
            if (!isInit)
                return; ;
            var datahelper = new DefectDataHelper();
            datahelper.setCurrentImageByImageType(ImageInfolist, CurrentImageType);

            var temp1 = CurrentImg; CurrentImg = null; CurrentImg = temp1;
        }

        public BaseCommand SaveReviewCommand
        {
            get => new BaseCommand((obj) =>
            {
                SaveDefect();
            });
        }

        public BaseCommand ShownTypeCMD
        {
            get => new BaseCommand((obj) =>
            {
                ShownType = (int)obj;
            });
        }
        public BaseCommand ShowGrayCMD
        {
            get => new BaseCommand((obj) =>
            {
                ShownType = 2;
            });
        }


        public BaseCommand AddDefectCommand
        {
            get => new BaseCommand((obj) =>
            {

            });
        }

        public BaseCommand SearchBatchCommand { get => new BaseCommand(SearchBatchCommand_Executed); }
        public void SearchBatchCommand_Executed(object obj)
        {
            QueryBatchList();
        }
        public BaseCommand DefectTypeConfigCommand { get => new BaseCommand(DefectTypeConfigCommand_Executed); }
        public void DefectTypeConfigCommand_Executed(object obj)
        {
            new VM_WindowConfig().ShowDialog();
        }


        public BaseCommand DeleteDefectCommand
        {
            get => new BaseCommand((obj) =>
            {
                var select_defects = SelectedImageDefects;
                if (select_defects.Any())
                {
                    //仅修改内存数据，点击保存的时候再保存到数据库
                    foreach (var image_defect in SelectedImageDefects.ToArray())
                    {
                        image_defect.is_user_delete = true;
                        image_defect.other1 = "delete";
                    }
                }

            });
        }

        #region 修改缺陷类型，需要配合弹窗回调

        public BaseCommand ModifyDefectCommand
        {
            get => new BaseCommand((obj) =>
            {
                var select_defects = SelectedImageDefects;
                if (select_defects.Any())
                {
                    RequestShowDialog?.Invoke(this, new ShowDialogEventArgs((type) =>
                    {
                        foreach (var image_defect in select_defects)
                        {
                            image_defect.type = type;
                            image_defect.other1 = "modify";
                        }
                    }));
                }
            });
        }
        public delegate void DialogCallback(int result);
        public event EventHandler<ShowDialogEventArgs> RequestShowDialog;

        public class ShowDialogEventArgs : EventArgs
        {
            // 定义一个回调委托
            public DialogCallback Callback { get; private set; }

            public ShowDialogEventArgs(DialogCallback callback)
            {
                Callback = callback;
            }
        }
        #endregion


        private void QueryBatchList()
        {
            Batchlist = new ObservableCollection<batch>(surfaceEntities.batch.AsNoTracking().Where(t => t.insert_time >= Start && t.insert_time <= End).OrderByDescending(o => o.insert_time).ToList());
            if (Batchlist.Count == 0)
                return;
                CurrentBatch = Batchlist[0];
        }
        public BaseCommand SearchSingleBatchCommand
        {
            get => new BaseCommand((obj) => {
                var batchid = obj as string;
                var batches = surfaceEntities.batch.Where(t => t.main_id == batchid || t.user_custom_id == batchid).ToList();
                if (batches.Any())
                    CurrentBatch = batches[0];
                else
                    MessageBox("未找到对应批次，请输入正确的批次号");
            });
        }

        private void QueryDefectCountList() {
            var defectcountlist_groupbytype= ImageInfolist.SelectMany(t => t.Image_DefectList).GroupBy(t => t.type).Select(t=>new DefectCount{ DefectType = t.Key,Count=t.Count() });
            DefectCountList=new ObservableCollection<DefectCount>(defectcountlist_groupbytype);
        }
        private void QueryCurrentImg()
        {
            var currentimg = ImageInfolist.Where(t => t.Image_DefectList.Contains(CurrentDefect)).FirstOrDefault();
            if (currentimg != null)
                CurrentImg = currentimg;
        }

        public void GotoReviewDefect(string main_id)
        {
            var list=surfaceEntities.batch.Where(t => t.main_id == main_id).ToList();
            if (list.Count == 1)
            {
                CurrentBatch = list.First();
            }
        }

    }

    public class DefectCount
    {
        public int DefectType { get; set; }
        public int Count { get; set; }


    }
}
